﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using static DLLPC.MotionHelper;
using DLLPC.Utilities;
using System.Net;
using System.Net.Sockets;
using System.Net;
//using System.Windows.Forms;
//using RRQMSocket;

namespace VisionCore
{
    public class CodeReaderHelper
    {
        TcpClient tcpClient=new TcpClient();
        string ip = "192.168.0.2";
        int port = 8001;
        
        private SystemTimeCounter sysTimer = new SystemTimeCounter();

        //public Action<string> CallBackEventHandler = null;

        public SafeQueue<byte[]> SQ_SendCMD = new SafeQueue<byte[]>();
        public bool Sending { get; set; } = false;

        public double CycleTime { get; set; } = 0;
        public CodeReaderHelper(string strip,int _port)
        {
            ip = strip;
            port = _port;           
        }


        Thread thread;
        private bool isRun = true;

        private bool isReadOK = false;

        public bool IsReadOK
        {
            get
            {
                return isReadOK;
            }

        }
        private string code=" ";

        /// <summary>
        /// 上-->下(近-->远)  +-->- 
        /// </summary>
        public string Code
        {
            set
            {
                code = value;
            }
            get
            {
                return code;
            }
        }


        private bool enable = true;
        public bool Enable
        {
            get { return enable; }
        }

        private bool connected = false;
        public bool Connected
        {
            get { return connected; }
        }

        public void Start(bool en = true)
        {
            enable = en;
            thread = new Thread(theadFunction);
            thread.IsBackground = true;
            thread.Start();
        }

        public void Quit()
        {
            isRun = false;
        }

        private PollStatus StatusCode = new PollStatus();
        /// <summary>
        /// 采样周期
        /// </summary>
        public double SamplePeriod { get; set; } = 0;
        public bool IsError { get; set; } = false;
        int RetryIdx = 0;
        int timecot = 0;

        private void theadFunction()
        {
            ProcessHelper.SetThreadAffinityMask(ProcessHelper.GetCurrentThread(), new UIntPtr(ProcessHelper.SetCpuID(4)));
            if (!Enable) return;

            StatusCode = PollStatus.Open;
            sysTimer.Start();
            while (isRun)
            {
                switch (StatusCode)
                {
                    case PollStatus.Open:
                        if (Connect() == false)
                        {
                            Thread.Sleep(2000);
                        }
                        else
                        {
                            LogMsg("连接成功！");
                            connected = true;
                            StatusCode = PollStatus.Initial;
                        }
                        break;
                    case PollStatus.Initial:
                        if (InitialFunction() == false)
                        {
                            StatusCode = PollStatus.Error;
                        }
                        else
                        {
                            tcpClient.Client.SendBufferSize = 16;
                            tcpClient.Client.ReceiveBufferSize = 32;
                            StatusCode = PollStatus.Polling;
                        }
                        break;
                    case PollStatus.Polling:
                        //if (timecot > 2)
                        //{
                        //    timecot = 0;
                        //    byte[] sendbytes = new byte[4];
                        //    sendbytes[0] = 0x30;
                        //    sendbytes[1] = 0x02;
                        //    sendbytes[2] = 0x0d;
                        //    sendbytes[3] = 0x60;
                        //    SQ_SendCMD.Enqueue(sendbytes);
                        //}
                        if (PollingFunction() == false)
                        {
                            if (RetryIdx > 3)
                            {
                                RetryIdx = 0;
                                StatusCode = PollStatus.Error;
                                Thread.Sleep(2000);
                            }
                            RetryIdx++;
                        }
                        else
                        {
                            RetryIdx = 0;
                        }
                        timecot++;
                        break;
                    case PollStatus.Error:
                        ErrorHandle();
                        connected = false;
                        StatusCode = PollStatus.Open;
                        break;
                    default:
                        break;
                }

                IsError = (StatusCode == PollStatus.Polling ? false : true);

                sysTimer.Stop();
                SamplePeriod = sysTimer.Duration;
                sysTimer.Start();

                SystemTimeCounter.timeBeginPeriod(1);
                Thread.Sleep(1);
                SystemTimeCounter.timeEndPeriod(1);
            }

            DisConnect();
        }

        public bool Connect()
        {
            IPAddress host = IPAddress.Parse(ip);
            try
            {
                if (tcpClient == null || tcpClient.Client == null)
                {
                    tcpClient = new TcpClient();
                }

                tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 200);
                tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 200);

                if (!tcpClient.Connected)
                {
                    tcpClient.Connect(host, port);

                    if (tcpClient.Client.Available > 0)
                    {
                        byte[] tReceiveData = new byte[512];
                        int tCount = tcpClient.Client.Receive(tReceiveData);
                        string tReturnData = ASCIIEncoding.ASCII.GetString(tReceiveData).Trim();
                        LogMsg(tReturnData);
                    }
                }

                return true;
            }
            catch (Exception ex)
            {
                LogMsg("TcpClient Connect Error: " + ex.Message);
                tcpClient.Close();
                return false;
            }



        }

        public void DisConnect()
        {
            try
            {
                if (tcpClient.Connected == true)
                {
                    tcpClient.Close();
                }
            }
            catch (Exception ex)
            {
                LogMsg("DisConnect error: " + ex.Message);
            }
        }
        int timecot1 = 0;

        private bool PollingFunction()
        {
            try
            {
                if (Sending)
                {
                    isReadOK = false;
                    code = " ";
                    Sending = false;
                    byte[] sendData =new byte[] { 0x54 };
                    tcpClient.Client.Send(sendData);
                }

                if (tcpClient.Client.Available > 0)
                {
                    Sending = false;
                    byte[] recvbytes = new byte[20];
                    int count = tcpClient.Client.Receive(recvbytes);
                    code = ASCIIEncoding.ASCII.GetString(recvbytes).Trim();
                    if (count > 6)
                    {
                        isReadOK = true;
                    }
                    else
                    {
                        isReadOK = false;
                    }

                    if (count != 6)
                    {
                        IsError = true;
                        return true;
                    }
                    

                }
                return true;
            }
            catch (Exception ex)
            {
                LogMsg("read value error:" + ex.Message);
                return false;
            }
        }


        private bool InitialFunction()
        {
            return true;
        }

        private void ErrorHandle()
        {
            LogMsg("通信错误");
            Thread.Sleep(4000);
        }

        private void LogMsg(string msg)
        {
            string strMsg = string.Format("读码器 {0}", msg);
            LogHelper.Write(LogHelper.Module.Motion, strMsg);
        }


    }
    internal enum PollStatus
    {
        Open = 0,
        Initial = 4,
        Polling = 10,
        Error = 30
    }
}
